<template>
	<view class="search-combox" :class="border ? '' : 'search-combox__no-border'">
		<view v-if="label" class="search-combox__label" :style="labelStyle">
			<text>{{ label }}</text>
		</view>
		<view class="search-combox__input-box">
			<input class="search-combox__input" type="text" :placeholder="placeholder"
				placeholder-class="search-combox__input-plac" v-model="inputVal" @input="onInput" @focus="onFocus"
				@blur="onBlur" />
			<uni-icons :type="showSelector ? 'top' : 'bottom'" size="14" color="#999"
				@click="toggleSelector"></uni-icons>
		</view>
		<view class="search-combox__selector" v-if="showSelector">
			<view class="uni-popper__arrow"></view>
			<scroll-view scroll-y="true" class="search-combox__selector-scroll">
				<view class="search-combox__selector-empty" v-if="filterCandidatesLength === 0">
					<text>{{ emptyTips }}</text>
				</view>
				<view class="search-combox__selector-item" v-for="(item, index) in filterCandidates" :key="index"
					@click="onSelectorClick(index)">
					<text :style="
              (
                isJSON
                  ? item[keyName]
                    ? item[keyName] == inputVal
                    : false
                  : item == inputVal
              )
                ? 'font-weight: bold;background-color: ' +
                  selectedBackground +
                  ';color: ' +
                  selectedColor
                : ''
            ">
						{{
              isJSON
                ? item[keyName]
                  ? item[keyName]
                  : '字段' + keyName + '不存在'
                : item
            }}
					</text>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	import { watch, computed, ref } from 'vue'

	const props = defineProps({
		isJSON: {
			type: Boolean,
			default: false,
		},
		// 默认取text
		keyName: {
			type: String,
			default: 'text',
		},
		// 被选中的背景颜色
		selectedBackground: {
			type: String,
			default: '#e5e5e5',
		},
		// 被选中的字体颜色
		selectedColor: {
			type: String,
			default: '#3774c6',
		},
		// 选择输入框边框
		border: {
			type: Boolean,
			default: true,
		},
		// 前缀
		label: {
			type: String,
			default: '',
		},
		// 前缀宽度
		labelWidth: {
			type: String,
			default: 'auto',
		},
		// 提示文案
		placeholder: {
			type: String,
			default: '请选择',
		},
		candidates: {
			type: Array,
			/**
			 * default
			 */
			default: () => [],
		},
		// 无匹配项
		emptyTips: {
			type: String,
			default: '无匹配项',
		},
		// modelValue
		modelValue: {
			type: [String, Number],
			default: '',
		},
	})

	const emit = defineEmits(['update:modelValue', 'input', 'select'])
	const isInput = ref(false)
	const showSelector = ref(false)
	const inputVal = ref<any>('')

	const labelStyle = computed(() => {
		if (props.labelWidth === 'auto') {
			return ''
		}
		return `width: ${props.labelWidth}`
	})

	const filterCandidates : any = computed(() => {
		if (isInput.value) {
			if (props.isJSON) {
				return props.candidates.filter(
					(item : any) =>
						item[props.keyName].toString().indexOf(inputVal.value) > -1,
				)
			} else {
				return props.candidates.filter(
					(item : any) => item.toString().indexOf(inputVal.value) > -1,
				)
			}
		} else {
			return props.candidates
		}
	})

	const filterCandidatesLength = computed(() => filterCandidates.value.length)

	watch(
		() => props.modelValue,
		(newVal) => {
			inputVal.value = newVal
			isInput.value = true
		},
		{ immediate: true },
	)

	/**
	 * 点击展示选项
	 */
	const toggleSelector = () => {
		showSelector.value = !showSelector.value
		isInput.value = false
	}

	/**
	 * 获得焦点
	 */
	const onFocus = () => {
		showSelector.value = true
		isInput.value = false
	}

	/**
	 * 失去焦点
	 */
	const onBlur = () => {
		setTimeout(() => {
			showSelector.value = false
			isInput.value = false
		}, 153)
	}

	/**
	 * 选择事件
	 * @param index index
	 */
	const onSelectorClick = (index : any) => {
		const item : any = filterCandidates.value[index]
		inputVal.value = props.isJSON ? item[props.keyName] : item
		showSelector.value = false
		emit('update:modelValue', inputVal.value)
		emit('input', inputVal.value)
		emit('select', item)
	}

	/**
	 * 输入事件
	 */
	const onInput = () => {
		setTimeout(() => {
			emit('input', inputVal.value)
		})
	}
</script>

<style lang="scss" scoped>
	.search-combox {
		position: relative;
		display: flex;
		flex-direction: row;
		align-items: center;
		width: 158rpx;
		min-height: 24rpx;
		padding: 0 15rpx 0 20rpx;
		font-size: 28rpx;
		// border: 2rpx solid #e5e5e5;
		border-radius: 8rpx;
		background-color: #f0f0f0;
	}

	.search-combox__label {
		padding-right: 10rpx;
		color: #999999;
		font-size: 32rpx;
		line-height: 44rpx;
	}

	.search-combox__input-box {
		position: relative;
		display: flex;
		flex: 1;
		flex-direction: row;
		align-items: center;
	}

	.search-combox__input {
		flex: 1;
		height: 44rpx;
		font-size: 28rpx;
		line-height: 44rpx;
	}

	.search-combox__input-plac {
		color: #999;
		font-size: 24rpx;
	}

	.search-combox__selector {
		position: absolute;
		top: calc(100% + 24rpx);
		left: 0;
		z-index: 99999;
		box-sizing: border-box;
		width: 100%;
		height: 200rpx;
		padding: 8rpx 0;
		background-color: #ffffff;
		border: 2rpx solid #ebeef5;
		border-radius: 12rpx;
		box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.1);
	}

	.search-combox__selector-scroll {
		box-sizing: border-box;
		max-height: 140rpx;
	}

	.search-combox__selector-empty,
	.search-combox__selector-item {
		display: flex;
		padding: 0rpx 0rpx;
		font-size: 28rpx;
		line-height: 70rpx;
		text-indent: 1rem;
		cursor: pointer;
	}

	.search-combox__selector-empty text,
	.search-combox__selector-item text {
		width: 100%;
	}

	.search-combox__selector-item:hover {
		background-color: #e5e5e5;
	}

	.search-combox__selector-empty:last-child,
	.search-combox__selector-item:last-child {
		border-bottom: none;
	}

	// picker 弹出层通用的指示小三角
	.uni-popper__arrow,
	.uni-popper__arrow::after {
		position: absolute;
		display: block;
		width: 0;
		height: 0;
		border-color: transparent;
		border-style: solid;
		border-width: 12rpx;
	}

	.uni-popper__arrow {
		top: -12rpx;
		left: 80%;
		margin-right: 6rpx;
		border-top-width: 0;
		border-bottom-color: #ebeef5;
		filter: drop-shadow(0 4rpx 24rpx rgba(0, 0, 0, 0.03));
	}

	.uni-popper__arrow::after {
		top: 2rpx;
		margin-left: -12rpx;
		border-top-width: 0;
		border-bottom-color: #fff;
		content: ' ';
	}

	.search-combox__no-border {
		border: none;
	}
</style>